<h2><strong>Introduction</strong></h2>

<p><strong>Microsoft Crypto API</strong> (CAPI) was first released with the Windows NT4 operating system in 1996. The OpenSSL project, that was originally a fork of <a href="https://en.wikipedia.org/wiki/SSLeay">SSLeay</a> by Eric Young and Tim Hudson, was initiated in 1998 and has since become one of the most widely distributed cryptographic libraries available.</p>

<p>I recently required a Windows application using CAPI that can sign and verify files using the RSA digital signature algorithm, but it needed to read RSA keys and signatures generated by OpenSSL. The keys are stored using <strong><span class="_Tgc">Abstract Syntax Notation One</span> </strong> (ASN.1) and <strong>Privacy Enhanced Mail</strong> (PEM) format. The signatures are stored in binary using big-endian convention.</p>

<p>In this post, we'll focus specifically on RSA key generation, the importation/exportation of RSA keys and the key management standards used to exchange keys in a platform independent manner. I understand RSA is being phased out in favor of Elliptic Curve Cryptography (ECC) that may be discussed in a future post. I'm also aware ECC will eventually be phased out in favor of quantum resistant cryptography which is still under a lot of research and development, but that could be 10+ years away and RSA still offers good security margin, albeit with less efficiency.</p>

<p>Part 2 will focus specifically on generation and exchange of session keys over TCP for symmetric encryption, but the bulk of work needed to reach that stage is really within this post.</p>

<h2><strong>Key Management Standards</strong></h2>

<p>The 2 main issues developers appear to complain about for interoperability between OpenSSL and Microsoft Crypto API are:</p>

<ol>
 	<li>Signatures exported by OpenSSL functions use big-endian convention, Microsoft Crypto API uses little-endian</li>
 	<li>Public and Private Keys exported by OpenSSL functions use ASN.1 structures, Microsoft CryptoAPI use their own structures or what are referred to as "Blobs"</li>
</ol>

<p>However, both API support the following standards for public key management:</p>

<ul>
 	<li><strong><a href="https://tools.ietf.org/rfc/rfc5208.txt">PKCS #8: Private-Key Information Syntax Standard</a></strong></li>
 	<li><strong><a href="https://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf">ASN.1 encoding rules: Specification of Basic Encoding Rules (BER), Canonical Encoding Rules (CER) and Distinguished Encoding Rules (DER)</a></strong></li>
</ul>

<p>We just need to import and export keys using these standard formats to successfully exchange keys between the 2 API. Then there's the issue of textual encoding using <em>Privacy Enhanced Mail</em> (PEM) format which is defined in <a href="http://www.rfc-base.org/txt/rfc-1421.txt">RFC1421</a>, <a href="http://www.rfc-base.org/txt/rfc-1422.txt">RFC1422</a> and <a href="http://www.rfc-base.org/txt/rfc-1423.txt">RFC1423</a>. Essentially, this encoding uses the base64 algorithm.</p>

<h2><strong>RSA Digital Signatures and RSA Key Exchange</strong></h2>

<p>When signing a file, we derive a cryptographic hash from its data. This hash is then encrypted using an RSA private key and modular exponentiation. The resulting ciphertext is called a signature. Verification of the signature involves decryption using an RSA public key and Modular Exponentiation. When exchanging session keys, the client side will generate a value derived from a cryptographic pseudo-random number generator (CSPRNG). This value will be used as the symmetric encryption key. It's then encrypted using an RSA public key and modular exponentiatation before being sent to a remote server. The server will perform RSA decryption using the private key to recover the same session key.</p>

<h2><strong>Byte Order</strong></h2>

<p>OpenSSL exports signatures using the Big-Endian convention whereas Microsoft Crypto API uses Little-Endian. High end servers and mainframes in the 80s and 90s used Big-Endian architectures like SPARC, MIPS and POWER. The legacy of this are many cryptography libraries using Big-Endian convention to store data on disk. To accomodate this on Windows which predominantly runs on X86 architecture, we use the following piece of code to swap the order of bytes after signing and before verification. Then we have no problem verifying signatures generated by OpenSSL.</p>

<pre style='color:#000000;background:#ffffff;'><span style='color:#696969;'>// used to convert digital signature from big-endian to little-endian</span>
<span style='color:#800000;font-weight:bold;'>void</span> byte_swap<span style='color:#808030;'>(</span><span style='color:#800000;font-weight:bold;'>void</span> <span style='color:#808030;'>*</span>buf<span style='color:#808030;'>,</span> <span style='color:#800000;font-weight:bold;'>int</span> len<span style='color:#808030;'>)</span> <span style='color:#800080;'>{</span>
    <span style='color:#800000;font-weight:bold;'>int</span>     i<span style='color:#800080;'>;</span>
    uint8_t t<span style='color:#808030;'>,</span> <span style='color:#808030;'>*</span>p<span style='color:#808030;'>=</span><span style='color:#808030;'>(</span>uint8_t<span style='color:#808030;'>*</span><span style='color:#808030;'>)</span>buf<span style='color:#800080;'>;</span>
    
    <span style='color:#800000;font-weight:bold;'>for</span><span style='color:#808030;'>(</span>i<span style='color:#808030;'>=</span><span style='color:#008c00;'>0</span><span style='color:#800080;'>;</span> i<span style='color:#808030;'>&lt;</span>len<span style='color:#808030;'>/</span><span style='color:#008c00;'>2</span><span style='color:#800080;'>;</span> i<span style='color:#808030;'>+</span><span style='color:#808030;'>+</span><span style='color:#808030;'>)</span> <span style='color:#800080;'>{</span>
      t <span style='color:#808030;'>=</span> p<span style='color:#808030;'>[</span>i<span style='color:#808030;'>]</span><span style='color:#800080;'>;</span> 
      p<span style='color:#808030;'>[</span>i<span style='color:#808030;'>]</span> <span style='color:#808030;'>=</span> p<span style='color:#808030;'>[</span>len <span style='color:#808030;'>-</span> <span style='color:#008c00;'>1</span> <span style='color:#808030;'>-</span> i<span style='color:#808030;'>]</span><span style='color:#800080;'>;</span>
      p<span style='color:#808030;'>[</span>len <span style='color:#808030;'>-</span> <span style='color:#008c00;'>1</span> <span style='color:#808030;'>-</span> i<span style='color:#808030;'>]</span> <span style='color:#808030;'>=</span> t<span style='color:#800080;'>;</span>
    <span style='color:#800080;'>}</span>
<span style='color:#800080;'>}</span>
</pre>

<h2><strong>RSA key context</strong></h2>

<p>The following structure is defined to hold RSA keys.</p>

<pre style='color:#000000;background:#ffffff;'><span style='color:#800000;font-weight:bold;'>typedef</span> <span style='color:#800000;font-weight:bold;'>struct</span> _RSA_CTX_t <span style='color:#800080;'>{</span>
<span style='color:#004a43;'>&#xa0;&#xa0;</span><span style='color:#004a43;'>#</span><span style='color:#004a43;'>ifdef</span><span style='color:#004a43;'> CAPI</span>
    HCRYPTPROV prov<span style='color:#800080;'>;</span>
    HCRYPTKEY  privkey<span style='color:#808030;'>,</span> pubkey<span style='color:#800080;'>;</span>
    HCRYPTHASH hash<span style='color:#800080;'>;</span>
    <span style='color:#603000;'>DWORD</span>      error<span style='color:#800080;'>;</span>
<span style='color:#004a43;'>&#xa0;&#xa0;</span><span style='color:#004a43;'>#</span><span style='color:#004a43;'>else</span>
    EVP_PKEY   <span style='color:#808030;'>*</span>pkey<span style='color:#800080;'>;</span>
<span style='color:#004a43;'>&#xa0;&#xa0;</span><span style='color:#004a43;'>#</span><span style='color:#004a43;'>endif</span><span style='color:#004a43;'>    </span>
<span style='color:#800080;'>}</span> RSA_CTX<span style='color:#808030;'>,</span> PRSA_CTX<span style='color:#800080;'>;</span>
</pre>

<h2><strong>RSA Key Generation</strong></h2>

<p>CAPI uses 65537 as the public exponent in key generation so we need to use the same for OpenSSL.</p>

<pre style='color:#000000;background:#ffffff;'><span style='color:#800000;font-weight:bold;'>int</span> RSA_genkey<span style='color:#808030;'>(</span>RSA_CTX<span style='color:#808030;'>*</span> ctx<span style='color:#808030;'>,</span> <span style='color:#800000;font-weight:bold;'>int</span> keyLen<span style='color:#808030;'>)</span> <span style='color:#800080;'>{</span>
<span style='color:#004a43;'>&#xa0;&#xa0;&#xa0;&#xa0;</span><span style='color:#004a43;'>#</span><span style='color:#004a43;'>ifndef</span><span style='color:#004a43;'> CAPI</span>
      BIGNUM <span style='color:#808030;'>*</span>e<span style='color:#808030;'>=</span><span style='color:#7d0045;'>NULL</span><span style='color:#800080;'>;</span>
      RSA    <span style='color:#808030;'>*</span>rsa<span style='color:#800080;'>;</span>
<span style='color:#004a43;'>&#xa0;&#xa0;&#xa0;&#xa0;</span><span style='color:#004a43;'>#</span><span style='color:#004a43;'>endif</span><span style='color:#004a43;'>  </span>
    <span style='color:#800000;font-weight:bold;'>int</span> ok<span style='color:#808030;'>=</span><span style='color:#008c00;'>0</span><span style='color:#800080;'>;</span>  
    <span style='color:#800000;font-weight:bold;'>if</span> <span style='color:#808030;'>(</span>ctx<span style='color:#808030;'>=</span><span style='color:#808030;'>=</span><span style='color:#7d0045;'>NULL</span><span style='color:#808030;'>)</span> <span style='color:#800000;font-weight:bold;'>return</span> <span style='color:#008c00;'>0</span><span style='color:#800080;'>;</span>
        
<span style='color:#004a43;'>&#xa0;&#xa0;&#xa0;&#xa0;</span><span style='color:#004a43;'>#</span><span style='color:#004a43;'>ifdef</span><span style='color:#004a43;'> CAPI</span>
      <span style='color:#696969;'>// 1. release public if already allocated</span>
      <span style='color:#800000;font-weight:bold;'>if</span> <span style='color:#808030;'>(</span>ctx<span style='color:#808030;'>-</span><span style='color:#808030;'>&gt;</span>pubkey <span style='color:#808030;'>!</span><span style='color:#808030;'>=</span> <span style='color:#008c00;'>0</span><span style='color:#808030;'>)</span> <span style='color:#800080;'>{</span>
        <span style='color:#400000;'>CryptDestroyKey</span><span style='color:#808030;'>(</span>ctx<span style='color:#808030;'>-</span><span style='color:#808030;'>&gt;</span>pubkey<span style='color:#808030;'>)</span><span style='color:#800080;'>;</span>
        ctx<span style='color:#808030;'>-</span><span style='color:#808030;'>&gt;</span>pubkey <span style='color:#808030;'>=</span> <span style='color:#008c00;'>0</span><span style='color:#800080;'>;</span>
      <span style='color:#800080;'>}</span>

      <span style='color:#696969;'>// 2. release private if already allocated</span>
      <span style='color:#800000;font-weight:bold;'>if</span> <span style='color:#808030;'>(</span>ctx<span style='color:#808030;'>-</span><span style='color:#808030;'>&gt;</span>privkey <span style='color:#808030;'>!</span><span style='color:#808030;'>=</span> <span style='color:#008c00;'>0</span><span style='color:#808030;'>)</span> <span style='color:#800080;'>{</span>
        <span style='color:#400000;'>CryptDestroyKey</span><span style='color:#808030;'>(</span>ctx<span style='color:#808030;'>-</span><span style='color:#808030;'>&gt;</span>privkey<span style='color:#808030;'>)</span><span style='color:#800080;'>;</span>
        ctx<span style='color:#808030;'>-</span><span style='color:#808030;'>&gt;</span>privkey <span style='color:#808030;'>=</span> <span style='color:#008c00;'>0</span><span style='color:#800080;'>;</span>
      <span style='color:#800080;'>}</span>

      <span style='color:#696969;'>// 3. generate key pair for digital signatures</span>
      ok <span style='color:#808030;'>=</span> <span style='color:#400000;'>CryptGenKey</span><span style='color:#808030;'>(</span>ctx<span style='color:#808030;'>-</span><span style='color:#808030;'>&gt;</span>prov<span style='color:#808030;'>,</span> AT_SIGNATURE<span style='color:#808030;'>,</span>
        <span style='color:#808030;'>(</span>keyLen <span style='color:#808030;'>&lt;</span><span style='color:#808030;'>&lt;</span> <span style='color:#008c00;'>16</span><span style='color:#808030;'>)</span> <span style='color:#808030;'>|</span> CRYPT_EXPORTABLE<span style='color:#808030;'>,</span>
        <span style='color:#808030;'>&amp;</span>ctx<span style='color:#808030;'>-</span><span style='color:#808030;'>&gt;</span>privkey<span style='color:#808030;'>)</span><span style='color:#800080;'>;</span>
<span style='color:#004a43;'>&#xa0;&#xa0;&#xa0;&#xa0;</span><span style='color:#004a43;'>#</span><span style='color:#004a43;'>else</span>
      <span style='color:#696969;'>// 1. initialize public exponent</span>
      BN_dec2bn<span style='color:#808030;'>(</span><span style='color:#808030;'>&amp;</span>e<span style='color:#808030;'>,</span> <span style='color:#800000;'>"</span><span style='color:#0000e6;'>65537</span><span style='color:#800000;'>"</span><span style='color:#808030;'>)</span><span style='color:#800080;'>;</span>
      
      <span style='color:#696969;'>// 2. create new RSA context</span>
      rsa <span style='color:#808030;'>=</span> RSA_new<span style='color:#808030;'>(</span><span style='color:#808030;'>)</span><span style='color:#800080;'>;</span> 
      
      <span style='color:#696969;'>// 3. generate key pair for digital signatures</span>
      <span style='color:#800000;font-weight:bold;'>if</span> <span style='color:#808030;'>(</span>RSA_generate_key_ex<span style='color:#808030;'>(</span>rsa<span style='color:#808030;'>,</span> keyLen<span style='color:#808030;'>,</span> e<span style='color:#808030;'>,</span> <span style='color:#7d0045;'>NULL</span><span style='color:#808030;'>)</span><span style='color:#808030;'>)</span> <span style='color:#800080;'>{</span>
        <span style='color:#696969;'>// 4. create new EVP key context</span>
        <span style='color:#800000;font-weight:bold;'>if</span> <span style='color:#808030;'>(</span><span style='color:#808030;'>(</span>ctx<span style='color:#808030;'>-</span><span style='color:#808030;'>&gt;</span>pkey <span style='color:#808030;'>=</span> EVP_PKEY_new<span style='color:#808030;'>(</span><span style='color:#808030;'>)</span><span style='color:#808030;'>)</span> <span style='color:#808030;'>!</span><span style='color:#808030;'>=</span> <span style='color:#7d0045;'>NULL</span><span style='color:#808030;'>)</span> <span style='color:#800080;'>{</span>
          <span style='color:#696969;'>// 5. assign RSA context to EVP key context        </span>
          ok <span style='color:#808030;'>=</span> EVP_PKEY_assign_RSA<span style='color:#808030;'>(</span>ctx<span style='color:#808030;'>-</span><span style='color:#808030;'>&gt;</span>pkey<span style='color:#808030;'>,</span> rsa<span style='color:#808030;'>)</span><span style='color:#800080;'>;</span>
        <span style='color:#800080;'>}</span>
      <span style='color:#800080;'>}</span>
      BN_free<span style='color:#808030;'>(</span>e<span style='color:#808030;'>)</span><span style='color:#800080;'>;</span>    
<span style='color:#004a43;'>&#xa0;&#xa0;&#xa0;&#xa0;</span><span style='color:#004a43;'>#</span><span style='color:#004a43;'>endif</span>
    <span style='color:#800000;font-weight:bold;'>return</span> ok<span style='color:#800080;'>;</span>  
<span style='color:#800080;'>}</span>
</pre>

<h2><strong>Reading and writing PEM files</strong></h2>

<p>Before using the CAPI functions, we need to decode the PEM files into ASN.1 encoded structures. The CryptStringToBinary and CryptBinaryToString APIs can convert to and from PEM, however these were only made available since Windows XP and Windows 2003. See PEM_read_file and PEM_write_file functions for more details.</p>

<h2><strong>Importing public and private keys</strong></h2>

<ul>
 	<li>Crypto API</li>
</ul>

<p>For the Public key, decode the ASN.1 structure into a <em>Public Key Info</em> structure before importing to CAPI key object using CryptImportPublicKeyInfo API.</p>

<pre style='color:#000000;background:#ffffff;'>        <span style='color:#696969;'>// 1. convert DER to RSA public key info</span>
        <span style='color:#800000;font-weight:bold;'>if</span> <span style='color:#808030;'>(</span>CryptDecodeObjectEx<span style='color:#808030;'>(</span>
            X509_ASN_ENCODING <span style='color:#808030;'>|</span> PKCS_7_ASN_ENCODING<span style='color:#808030;'>,</span>
            X509_PUBLIC_KEY_INFO<span style='color:#808030;'>,</span> derData<span style='color:#808030;'>,</span> derLen<span style='color:#808030;'>,</span>
            CRYPT_DECODE_ALLOC_FLAG<span style='color:#808030;'>,</span> <span style='color:#7d0045;'>NULL</span><span style='color:#808030;'>,</span>
            <span style='color:#808030;'>&amp;</span>keyData<span style='color:#808030;'>,</span> <span style='color:#808030;'>&amp;</span>keyLen<span style='color:#808030;'>)</span><span style='color:#808030;'>)</span>
        <span style='color:#800080;'>{</span>
          <span style='color:#696969;'>// 2. import public key blob</span>
          ok <span style='color:#808030;'>=</span> CryptImportPublicKeyInfo<span style='color:#808030;'>(</span>ctx<span style='color:#808030;'>-</span><span style='color:#808030;'>&gt;</span>prov<span style='color:#808030;'>,</span> 
             X509_ASN_ENCODING<span style='color:#808030;'>,</span>
            <span style='color:#808030;'>(</span>PCERT_PUBLIC_KEY_INFO<span style='color:#808030;'>)</span>keyData<span style='color:#808030;'>,</span> <span style='color:#808030;'>&amp;</span>ctx<span style='color:#808030;'>-</span><span style='color:#808030;'>&gt;</span>pubkey<span style='color:#808030;'>)</span><span style='color:#800080;'>;</span>

          <span style='color:#696969;'>// 3. release allocated memory</span>
          <span style='color:#400000;'>LocalFree</span><span style='color:#808030;'>(</span>keyData<span style='color:#808030;'>)</span><span style='color:#800080;'>;</span>
        <span style='color:#800080;'>}</span>
</pre>

<p>For the Private Key, decode the ASN.1 structure into a <em>Private Key Info</em> structure. Convert the PrivateKey value into a CAPI Private Key Blob before importing into a CAPI key object. Unfortunately, there's no CryptImportPrivateKeyInfo API, hence the extra call to CryptDecodeObjectEx.</p>

<pre style='color:#000000;background:#ffffff;'>        <span style='color:#696969;'>// 1. convert PKCS8 data to private key info</span>
        <span style='color:#800000;font-weight:bold;'>if</span><span style='color:#808030;'>(</span>CryptDecodeObjectEx<span style='color:#808030;'>(</span>
          X509_ASN_ENCODING<span style='color:#808030;'>,</span>
          PKCS_PRIVATE_KEY_INFO<span style='color:#808030;'>,</span>
          derData<span style='color:#808030;'>,</span> derLen<span style='color:#808030;'>,</span>
          CRYPT_DECODE_ALLOC_FLAG<span style='color:#808030;'>,</span>
          <span style='color:#7d0045;'>NULL</span><span style='color:#808030;'>,</span> <span style='color:#808030;'>&amp;</span>pki<span style='color:#808030;'>,</span> <span style='color:#808030;'>&amp;</span>pkiLen<span style='color:#808030;'>)</span><span style='color:#808030;'>)</span>
        <span style='color:#800080;'>{</span>
          <span style='color:#696969;'>// 2. convert private key info to RSA private key blob</span>
          <span style='color:#800000;font-weight:bold;'>if</span><span style='color:#808030;'>(</span>CryptDecodeObjectEx<span style='color:#808030;'>(</span>
            X509_ASN_ENCODING <span style='color:#808030;'>|</span> PKCS_7_ASN_ENCODING<span style='color:#808030;'>,</span>
            PKCS_RSA_PRIVATE_KEY<span style='color:#808030;'>,</span>
            pki<span style='color:#808030;'>-</span><span style='color:#808030;'>&gt;</span>PrivateKey<span style='color:#808030;'>.</span>pbData<span style='color:#808030;'>,</span> 
            pki<span style='color:#808030;'>-</span><span style='color:#808030;'>&gt;</span>PrivateKey<span style='color:#808030;'>.</span>cbData<span style='color:#808030;'>,</span>
            CRYPT_DECODE_ALLOC_FLAG<span style='color:#808030;'>,</span>
            <span style='color:#7d0045;'>NULL</span><span style='color:#808030;'>,</span> <span style='color:#808030;'>&amp;</span>keyData<span style='color:#808030;'>,</span> <span style='color:#808030;'>&amp;</span>keyLen<span style='color:#808030;'>)</span><span style='color:#808030;'>)</span>
          <span style='color:#800080;'>{</span>
            <span style='color:#696969;'>// 3. import private key blob</span>
            ok <span style='color:#808030;'>=</span> <span style='color:#400000;'>CryptImportKey</span><span style='color:#808030;'>(</span>
              ctx<span style='color:#808030;'>-</span><span style='color:#808030;'>&gt;</span>prov<span style='color:#808030;'>,</span> 
              keyData<span style='color:#808030;'>,</span> keyLen<span style='color:#808030;'>,</span> <span style='color:#008c00;'>0</span><span style='color:#808030;'>,</span>
              CRYPT_EXPORTABLE<span style='color:#808030;'>,</span> 
              <span style='color:#808030;'>&amp;</span>ctx<span style='color:#808030;'>-</span><span style='color:#808030;'>&gt;</span>privkey<span style='color:#808030;'>)</span><span style='color:#800080;'>;</span>
              
            <span style='color:#400000;'>LocalFree</span><span style='color:#808030;'>(</span>keyData<span style='color:#808030;'>)</span><span style='color:#800080;'>;</span>
          <span style='color:#800080;'>}</span>
          <span style='color:#400000;'>LocalFree</span><span style='color:#808030;'>(</span>pki<span style='color:#808030;'>)</span><span style='color:#800080;'>;</span>
        <span style='color:#800080;'>}</span>
</pre>

<ul>
 	<li>OpenSSL</li>
</ul>

<p>OpenSSL offers a much simpler solution with a single API call for both private and public keys. We also don't have to decode the PEM format before hand. Nice, eh?</p>

<pre style='color:#000000;background:#ffffff;'>    <span style='color:#603000;'>FILE</span> <span style='color:#808030;'>*</span>fd <span style='color:#808030;'>=</span> <span style='color:#603000;'>fopen</span><span style='color:#808030;'>(</span>ifile<span style='color:#808030;'>,</span> <span style='color:#800000;'>"</span><span style='color:#0000e6;'>rb</span><span style='color:#800000;'>"</span><span style='color:#808030;'>)</span><span style='color:#800080;'>;</span>
  
    <span style='color:#800000;font-weight:bold;'>if</span> <span style='color:#808030;'>(</span>fd <span style='color:#808030;'>!</span><span style='color:#808030;'>=</span> <span style='color:#7d0045;'>NULL</span><span style='color:#808030;'>)</span> <span style='color:#800080;'>{</span>
      <span style='color:#696969;'>// private key for signing?</span>
      <span style='color:#800000;font-weight:bold;'>if</span> <span style='color:#808030;'>(</span>pemType <span style='color:#808030;'>=</span><span style='color:#808030;'>=</span> RSA_PRIVATE_KEY<span style='color:#808030;'>)</span> <span style='color:#800080;'>{</span>
        ctx<span style='color:#808030;'>-</span><span style='color:#808030;'>&gt;</span>pkey <span style='color:#808030;'>=</span> PEM_read_PrivateKey<span style='color:#808030;'>(</span>fd<span style='color:#808030;'>,</span> <span style='color:#7d0045;'>NULL</span><span style='color:#808030;'>,</span> <span style='color:#7d0045;'>NULL</span><span style='color:#808030;'>,</span> <span style='color:#7d0045;'>NULL</span><span style='color:#808030;'>)</span><span style='color:#800080;'>;</span>
      <span style='color:#696969;'>// public key for verifying?  </span>
      <span style='color:#800080;'>}</span> <span style='color:#800000;font-weight:bold;'>else</span> <span style='color:#800000;font-weight:bold;'>if</span> <span style='color:#808030;'>(</span>pemType <span style='color:#808030;'>=</span><span style='color:#808030;'>=</span> RSA_PUBLIC_KEY<span style='color:#808030;'>)</span> <span style='color:#800080;'>{</span>
        ctx<span style='color:#808030;'>-</span><span style='color:#808030;'>&gt;</span>pkey <span style='color:#808030;'>=</span> PEM_read_PUBKEY<span style='color:#808030;'>(</span>fd<span style='color:#808030;'>,</span> <span style='color:#7d0045;'>NULL</span><span style='color:#808030;'>,</span> <span style='color:#7d0045;'>NULL</span><span style='color:#808030;'>,</span> <span style='color:#7d0045;'>NULL</span><span style='color:#808030;'>)</span><span style='color:#800080;'>;</span>
      <span style='color:#800080;'>}</span>
      ok <span style='color:#808030;'>=</span> <span style='color:#808030;'>(</span>ctx<span style='color:#808030;'>-</span><span style='color:#808030;'>&gt;</span>pkey <span style='color:#808030;'>!</span><span style='color:#808030;'>=</span> <span style='color:#7d0045;'>NULL</span><span style='color:#808030;'>)</span><span style='color:#800080;'>;</span>
      <span style='color:#603000;'>fclose</span><span style='color:#808030;'>(</span>fd<span style='color:#808030;'>)</span><span style='color:#800080;'>;</span>
    <span style='color:#800080;'>}</span>
</pre>

<h2><strong>Exporting keys</strong></h2>

<ul>
 	<li>Crypto API</li>
</ul>

<p>Since 2000, we can use CryptExportPKCS8 to export the private key.</p>

<pre style='color:#000000;background:#ffffff;'>      <span style='color:#696969;'>// 1. calculate size of PKCS#8 structure</span>
      <span style='color:#800000;font-weight:bold;'>if</span><span style='color:#808030;'>(</span>CryptExportPKCS8<span style='color:#808030;'>(</span>
        ctx<span style='color:#808030;'>-</span><span style='color:#808030;'>&gt;</span>prov<span style='color:#808030;'>,</span> AT_SIGNATURE<span style='color:#808030;'>,</span> szOID_RSA_RSA<span style='color:#808030;'>,</span> 
        <span style='color:#008c00;'>0</span><span style='color:#808030;'>,</span> <span style='color:#7d0045;'>NULL</span><span style='color:#808030;'>,</span> <span style='color:#7d0045;'>NULL</span><span style='color:#808030;'>,</span> <span style='color:#808030;'>&amp;</span>pkiLen<span style='color:#808030;'>)</span><span style='color:#808030;'>)</span>
      <span style='color:#800080;'>{</span>
        pki <span style='color:#808030;'>=</span> <span style='color:#603000;'>malloc</span><span style='color:#808030;'>(</span>pkiLen<span style='color:#808030;'>)</span><span style='color:#800080;'>;</span>
        
        <span style='color:#800000;font-weight:bold;'>if</span><span style='color:#808030;'>(</span>pki <span style='color:#808030;'>!</span><span style='color:#808030;'>=</span> <span style='color:#7d0045;'>NULL</span><span style='color:#808030;'>)</span> <span style='color:#800080;'>{</span>
          <span style='color:#696969;'>// 2. export PKCS#8 structure to memory</span>
          ok <span style='color:#808030;'>=</span> CryptExportPKCS8<span style='color:#808030;'>(</span>
                ctx<span style='color:#808030;'>-</span><span style='color:#808030;'>&gt;</span>prov<span style='color:#808030;'>,</span> AT_SIGNATURE<span style='color:#808030;'>,</span> szOID_RSA_RSA<span style='color:#808030;'>,</span> 
                <span style='color:#008c00;'>0</span><span style='color:#808030;'>,</span> <span style='color:#7d0045;'>NULL</span><span style='color:#808030;'>,</span> pki<span style='color:#808030;'>,</span> <span style='color:#808030;'>&amp;</span>pkiLen<span style='color:#808030;'>)</span><span style='color:#800080;'>;</span>
          <span style='color:#800000;font-weight:bold;'>if</span><span style='color:#808030;'>(</span>ok<span style='color:#808030;'>)</span> <span style='color:#800080;'>{</span>
            <span style='color:#696969;'>// 3. write memory to file in PEM format</span>
            PEM_write_file<span style='color:#808030;'>(</span>RSA_PRIVATE_KEY<span style='color:#808030;'>,</span> 
                ofile<span style='color:#808030;'>,</span> pki<span style='color:#808030;'>,</span> pkiLen<span style='color:#808030;'>)</span><span style='color:#800080;'>;</span>
          <span style='color:#800080;'>}</span>
          <span style='color:#603000;'>free</span><span style='color:#808030;'>(</span>pki<span style='color:#808030;'>)</span><span style='color:#800080;'>;</span>
        <span style='color:#800080;'>}</span>
      <span style='color:#800080;'>}</span>
</pre>

<p>Exporting the public key using CryptExportPublicKeyInfo before encoding with ASN.1.</p>

<pre style='color:#000000;background:#ffffff;'>      <span style='color:#696969;'>// 1. get size of public key info</span>
      <span style='color:#800000;font-weight:bold;'>if</span> <span style='color:#808030;'>(</span>CryptExportPublicKeyInfo<span style='color:#808030;'>(</span>ctx<span style='color:#808030;'>-</span><span style='color:#808030;'>&gt;</span>prov<span style='color:#808030;'>,</span> 
          AT_SIGNATURE<span style='color:#808030;'>,</span>
          X509_ASN_ENCODING <span style='color:#808030;'>|</span> PKCS_7_ASN_ENCODING<span style='color:#808030;'>,</span>
          <span style='color:#7d0045;'>NULL</span><span style='color:#808030;'>,</span> <span style='color:#808030;'>&amp;</span>pkiLen<span style='color:#808030;'>)</span><span style='color:#808030;'>)</span>
      <span style='color:#800080;'>{</span>
        <span style='color:#696969;'>// 2. allocate memory</span>
        pki <span style='color:#808030;'>=</span> <span style='color:#603000;'>malloc</span><span style='color:#808030;'>(</span>pkiLen<span style='color:#808030;'>)</span><span style='color:#800080;'>;</span>

        <span style='color:#696969;'>// 3. export public key info</span>
        <span style='color:#800000;font-weight:bold;'>if</span> <span style='color:#808030;'>(</span>CryptExportPublicKeyInfo<span style='color:#808030;'>(</span>ctx<span style='color:#808030;'>-</span><span style='color:#808030;'>&gt;</span>prov<span style='color:#808030;'>,</span> 
            AT_SIGNATURE<span style='color:#808030;'>,</span>
            X509_ASN_ENCODING <span style='color:#808030;'>|</span> PKCS_7_ASN_ENCODING<span style='color:#808030;'>,</span>
            pki<span style='color:#808030;'>,</span> <span style='color:#808030;'>&amp;</span>pkiLen<span style='color:#808030;'>)</span><span style='color:#808030;'>)</span>
        <span style='color:#800080;'>{</span>
          <span style='color:#696969;'>// 4. get size of DER encoding</span>
          <span style='color:#800000;font-weight:bold;'>if</span> <span style='color:#808030;'>(</span>CryptEncodeObjectEx<span style='color:#808030;'>(</span>
            X509_ASN_ENCODING <span style='color:#808030;'>|</span> PKCS_7_ASN_ENCODING<span style='color:#808030;'>,</span>
            X509_PUBLIC_KEY_INFO<span style='color:#808030;'>,</span> pki<span style='color:#808030;'>,</span> <span style='color:#008c00;'>0</span><span style='color:#808030;'>,</span>
            <span style='color:#7d0045;'>NULL</span><span style='color:#808030;'>,</span> <span style='color:#7d0045;'>NULL</span><span style='color:#808030;'>,</span> <span style='color:#808030;'>&amp;</span>derLen<span style='color:#808030;'>)</span><span style='color:#808030;'>)</span>
          <span style='color:#800080;'>{</span>
            derData <span style='color:#808030;'>=</span> <span style='color:#603000;'>malloc</span><span style='color:#808030;'>(</span>derLen<span style='color:#808030;'>)</span><span style='color:#800080;'>;</span>
            <span style='color:#800000;font-weight:bold;'>if</span> <span style='color:#808030;'>(</span>derData<span style='color:#808030;'>)</span> <span style='color:#800080;'>{</span>
              <span style='color:#696969;'>// 5. convert to DER format</span>
              ok <span style='color:#808030;'>=</span> CryptEncodeObjectEx<span style='color:#808030;'>(</span>
                X509_ASN_ENCODING <span style='color:#808030;'>|</span> PKCS_7_ASN_ENCODING<span style='color:#808030;'>,</span>
                X509_PUBLIC_KEY_INFO<span style='color:#808030;'>,</span> pki<span style='color:#808030;'>,</span> <span style='color:#008c00;'>0</span><span style='color:#808030;'>,</span>
                <span style='color:#7d0045;'>NULL</span><span style='color:#808030;'>,</span> derData<span style='color:#808030;'>,</span> <span style='color:#808030;'>&amp;</span>derLen<span style='color:#808030;'>)</span><span style='color:#800080;'>;</span>

              <span style='color:#696969;'>// 6. write to PEM file</span>
              <span style='color:#800000;font-weight:bold;'>if</span> <span style='color:#808030;'>(</span>ok<span style='color:#808030;'>)</span> <span style='color:#800080;'>{</span>
                PEM_write_file<span style='color:#808030;'>(</span>RSA_PUBLIC_KEY<span style='color:#808030;'>,</span> 
                    ofile<span style='color:#808030;'>,</span> derData<span style='color:#808030;'>,</span> derLen<span style='color:#808030;'>)</span><span style='color:#800080;'>;</span>
              <span style='color:#800080;'>}</span>
            <span style='color:#800080;'>}</span>
            <span style='color:#603000;'>free</span><span style='color:#808030;'>(</span>derData<span style='color:#808030;'>)</span><span style='color:#800080;'>;</span>            
          <span style='color:#800080;'>}</span>
        <span style='color:#800080;'>}</span>
      <span style='color:#800080;'>}</span>
</pre>

<ul>
 	<li>OpenSSL</li>
</ul>

<pre style='color:#000000;background:#ffffff;'>      <span style='color:#603000;'>FILE</span> <span style='color:#808030;'>*</span>fd <span style='color:#808030;'>=</span> <span style='color:#603000;'>fopen</span><span style='color:#808030;'>(</span>ofile<span style='color:#808030;'>,</span> <span style='color:#800000;'>"</span><span style='color:#0000e6;'>wb</span><span style='color:#800000;'>"</span><span style='color:#808030;'>)</span><span style='color:#800080;'>;</span>
      <span style='color:#800000;font-weight:bold;'>if</span> <span style='color:#808030;'>(</span>fd <span style='color:#808030;'>!</span><span style='color:#808030;'>=</span> <span style='color:#7d0045;'>NULL</span><span style='color:#808030;'>)</span> <span style='color:#800080;'>{</span>
        <span style='color:#800000;font-weight:bold;'>if</span> <span style='color:#808030;'>(</span>pemType <span style='color:#808030;'>=</span><span style='color:#808030;'>=</span> RSA_PUBLIC_KEY<span style='color:#808030;'>)</span> <span style='color:#800080;'>{</span>
          ok <span style='color:#808030;'>=</span> PEM_write_PUBKEY<span style='color:#808030;'>(</span>fd<span style='color:#808030;'>,</span> ctx<span style='color:#808030;'>-</span><span style='color:#808030;'>&gt;</span>pkey<span style='color:#808030;'>)</span><span style='color:#800080;'>;</span>
        <span style='color:#800080;'>}</span> <span style='color:#800000;font-weight:bold;'>else</span> <span style='color:#800000;font-weight:bold;'>if</span> <span style='color:#808030;'>(</span>pemType <span style='color:#808030;'>=</span><span style='color:#808030;'>=</span> RSA_PRIVATE_KEY<span style='color:#808030;'>)</span> <span style='color:#800080;'>{</span>        
          ok <span style='color:#808030;'>=</span> PEM_write_PKCS8PrivateKey<span style='color:#808030;'>(</span>fd<span style='color:#808030;'>,</span> 
              ctx<span style='color:#808030;'>-</span><span style='color:#808030;'>&gt;</span>pkey<span style='color:#808030;'>,</span> <span style='color:#7d0045;'>NULL</span><span style='color:#808030;'>,</span> <span style='color:#7d0045;'>NULL</span><span style='color:#808030;'>,</span> <span style='color:#008c00;'>0</span><span style='color:#808030;'>,</span> <span style='color:#7d0045;'>NULL</span><span style='color:#808030;'>,</span> <span style='color:#7d0045;'>NULL</span><span style='color:#808030;'>)</span><span style='color:#800080;'>;</span>   
        <span style='color:#800080;'>}</span>
        <span style='color:#603000;'>fclose</span><span style='color:#808030;'>(</span>fd<span style='color:#808030;'>)</span><span style='color:#800080;'>;</span>
      <span style='color:#800080;'>}</span>  
</pre>

<h2><strong>Signing a file</strong></h2>
<ul>
 	<li>Crypto API</li>
</ul>

<img class="size-full wp-image-289 aligncenter" src="https://stosd.files.wordpress.com/2017/04/sign_capi.png" alt="" width="410" height="610" />
<ul>
 	<li>OpenSSL</li>
</ul>
<img class="size-full wp-image-290 aligncenter" src="https://stosd.files.wordpress.com/2017/04/sign_openssl.png" alt="" width="504" height="555" />
<h3><strong>Verifying signature</strong></h3>
<ul>
 	<li>Crypto API</li>
</ul>
<img class="size-full wp-image-293 aligncenter" src="https://stosd.files.wordpress.com/2017/04/verify_capi.png" alt="" width="462" height="329" />
<ul>
 	<li>OpenSSL</li>
</ul>
<img class="size-full wp-image-294 aligncenter" src="https://stosd.files.wordpress.com/2017/04/verify_openssl.png" alt="" width="558" height="608" />
<h3><strong>RSA Tool Usage</strong></h3>
<ul>
 	<li>Key Generation</li>
</ul>
&nbsp;

<img class="size-full wp-image-340 aligncenter" src="https://stosd.files.wordpress.com/2017/04/key_gen2.png" alt="" width="333" height="123" />
<ul>
 	<li>Signing a file</li>
</ul>
<img class="size-full wp-image-320 aligncenter" src="https://stosd.files.wordpress.com/2017/04/sign2.png" alt="" width="428" height="117" />
<ul>
 	<li>Verifying signature</li>
</ul>
<img class="size-full wp-image-321 aligncenter" src="https://stosd.files.wordpress.com/2017/04/verify2.png" alt="" width="423" height="120" />

<h2><strong>Summary</strong></h2>

<p>The purpose of this post was to cover the main problems of key exchange between OpenSSL and Microsoft Crypto API. For symmetric key exchange, so long as we use ASN.1 encoding for the exchange of public and private keys and remember that OpenSSL uses Big-Endian convention instead of Little-Endian by CAPI, there isn't a significant problem. In part 2, we'll examine how to perform End-To-End encryption of network traffic between a windows machine using Crypto API and Linux using OpenSSL. Source code for the RSA tool can be found <a href="https://github.com/odzhan/rsa">here</a></p>
